<?php
namespace Swiftx\Component\Router\Annotation;
use ReflectionClass;
use Swiftx\Interfaces\Ioc\Container;
use Swiftx\Interfaces\Router\Annotation;
use Swiftx\Interfaces\Router\Collection;
use Swiftx\Component\Router\Dispatcher\Method as DispatcherMethod;

/**
 * 路由分发器
 *
 * @author		胡永强  <odaytudio@gmail.com>
 * @since		2015-10-09
 * @copyright	Copyright (c) 2014-2015 Swiftx Inc.
 */
class Method implements Annotation {

    /**
     * 路由反射对象
     * @var ReflectionClass
     */
    protected $reflectionClass;

    /**
     * 依赖注入容器
     * @var Container
     */
    protected $container;

    /**
     * 设置注入容器
     * @param Container $container
     * @auto-injection
     */
    public function setContainer(Container $container){
        $this->container = $container;
    }

    /**
     * 设置待解析的类
     * @param ReflectionClass $class
     * @return mixed
     */
    public function setReflection(ReflectionClass $class){
        $this->reflectionClass = $class;
    }

    /**
     * 解析注解路由
     * @param Collection $collection
     * @param string[] $evn
     */
    public function parser(Collection $collection, array $evn = []){
        // 初始化数据
        $methods = $this->reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);
        $class_name = $this->reflectionClass->getName();
        $default_document = '/'.str_replace('\\','/',$class_name).'/';

        // 注册方法路由
        foreach($methods as $method){
            $document = $method->getDocComment();
            $params = [];
            if(preg_match_all('/@router\s+(\S+)\s+(\S+)\s+/', $document, $params)){

                /** @var DispatcherMethod $dispatcher */
                $dispatcher = $this->container->create(DispatcherMethod::class);
                $params = array_combine($params[1],$params[2]);

                // 检查 Host 配置项
                if(isset($params['host']))
                    $dispatcher->setHost($this->replaceEvn($params['host'], $evn));

                // 检查 Method 配置项
                if(isset($params['method']))
                    $dispatcher->setMethod($this->replaceEvn($params['method'], $evn));
                else $dispatcher->setMethod('get');

                // 检查 Document 配置项
                if(isset($params['document']))
                    $dispatcher->setDocument($this->replaceEvn($params['document'], $evn));
                else $dispatcher->setDocument($default_document.$method->getName());

                $method_name = $method->getName();
                $dispatcher->setResource($class_name, $method_name);
                $name = $class_name.'::'.$method_name;
                $collection->registerDispatcher($name, $dispatcher);

            }
        }
    }

    /**
     * 解析环境变量
     * @param string $value
     * @param array $evn
     * @return string
     */
    protected function replaceEvn(string $value, array $evn):string {
        foreach($evn as $key => $item)
            $value = str_replace('{$'.$key.'}', $item , $value);
        return $value;
    }

}